package killerqueen.game.objects;

import killerqueen.game.interfaces.ContactAdapter;
import killerqueen.game.interfaces.GameObject;
import killerqueen.game.main.GameMain;

import org.jbox2d.collision.shapes.PolygonShape;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.BodyType;
import org.jbox2d.dynamics.FixtureDef;
import org.jbox2d.dynamics.World;
import org.jbox2d.dynamics.contacts.Contact;
import org.newdawn.slick.Color;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Input;
import org.newdawn.slick.geom.Polygon;

public class Player implements GameObject {

	private PolygonShape box;
	private PolygonShape sensorBotBox;
	private PolygonShape sensorTopBox;

	private Body body;

	public int botContactCount = 0;
	public int topContactCount = 0;

	private float x;
	private float y;

	private long lastShotTime;
	private float shootingSpeed;
	private boolean facingRight; 

	public Player() {

	}

	@Override
	public void init(World world, String id) {
		BodyDef bodyDef = new BodyDef();
		bodyDef.position.set(x, y);
		bodyDef.type = BodyType.DYNAMIC;
		body = world.createBody(bodyDef);
		body.setFixedRotation(true);
		box = new PolygonShape();
		box.setAsBox(0.25f, 0.90f);

		FixtureDef fixtureDef = new FixtureDef();
		fixtureDef.shape = box;
		fixtureDef.density = 5;
		fixtureDef.friction = 0.1f;
		fixtureDef.restitution = 0.1f;
		fixtureDef.filter.groupIndex = -1;

		body.createFixture(fixtureDef);

		sensorBotBox = new PolygonShape();
		sensorBotBox.setAsBox(0.24f, 0.05f, new Vec2(0, -0.9f), 0);

		FixtureDef sensorBot = new FixtureDef();
		sensorBot.isSensor = true;
		sensorBot.shape = sensorBotBox;
		sensorBot.userData = new ContactAdapter() {
			@Override
			public void endContact(Contact arg0) {
				botContactCount--;
			}

			@Override
			public void beginContact(Contact arg0) {
				botContactCount++;
				checkCrush();
			}
		};

		body.createFixture(sensorBot);

		sensorTopBox = new PolygonShape();
		sensorTopBox.setAsBox(0.24f, 0.05f, new Vec2(0, +0.6f), 0);

		FixtureDef sensorTop = new FixtureDef();
		sensorTop.isSensor = true;
		sensorTop.shape = sensorTopBox;
		sensorTop.userData = new ContactAdapter() {
			@Override
			public void endContact(Contact arg0) {
				topContactCount--;
			}

			@Override
			public void beginContact(Contact arg0) {
				topContactCount++;
				checkCrush();
			}
		};
		body.createFixture(sensorTop);

		lastShotTime = System.currentTimeMillis();
		shootingSpeed = 300;
		facingRight = true;
	}

	private void checkCrush() {
		if (botContactCount > 0 && topContactCount > 0) {
			System.err.println("Crush");
		}
	}

	@Override
	public void input(Input input) {
		if (input.isKeyDown(Input.KEY_D)) {
			moveX(1);
			facingRight = true;
		}
		if (input.isKeyDown(Input.KEY_A)) {
			moveX(-1);
			facingRight = false;
		}
		if (input.isKeyPressed(Input.KEY_SPACE)) {
			jump();
		}
		if (input.isKeyDown(Input.KEY_S)) {
			moveY(-1);
		}
		if (input.isKeyDown(Input.KEY_W)) {
			moveY(1);
		}
		if (input.isKeyDown(Input.KEY_E)) {
			shoot();
		}
	}

	private void shoot() {
		long currentShotTime= System.currentTimeMillis();
		if (currentShotTime - lastShotTime> shootingSpeed) {
			Bullet bullet = new Bullet();
			Vec2 pos = body.getPosition();
			if(facingRight){
				bullet.setX(pos.x + 0.3f);
				bullet.setSpeed(new Vec2(25, 2));
			}else{
				bullet.setX(pos.x - 0.3f);
				bullet.setSpeed(new Vec2(-25, 2));
			}
			bullet.setY(pos.y);
			GameMain.insertObject(bullet);
			lastShotTime = currentShotTime; 
		}
	}

	@Override
	public void paint(Graphics g) {

		g.pushTransform();

		Polygon p = new Polygon();
		Polygon s = new Polygon();

		Vec2 pos = body.getPosition();
		float angle = body.getAngle();
		g.translate(pos.x, pos.y);
		g.rotate(0, 0, (float) Math.toDegrees(+angle));

		for (int i = 0; i < box.getVertexCount(); i++) {
			Vec2 vertex = box.getVertex(i);
			p.addPoint(vertex.x, vertex.y);
		}
		for (int i = 0; i < sensorBotBox.getVertexCount(); i++) {
			Vec2 vertex = sensorBotBox.getVertex(i);
			s.addPoint(vertex.x, vertex.y);
		}
		for (int i = 0; i < sensorTopBox.getVertexCount(); i++) {
			Vec2 vertex = sensorTopBox.getVertex(i);
			s.addPoint(vertex.x, vertex.y);
		}
		g.draw(s);
		g.setColor(Color.blue);
		g.fill(p);
		g.setColor(Color.black);
		g.draw(p);

		g.popTransform();

	}

	@Override
	public void update(long delta) {
		return;

	}

	public Body getBody() {
		return body;
	}

	public void jump() {
		if (botContactCount > 0) {
			body.applyLinearImpulse(new Vec2(0, 32f), body.getPosition());
		}
	}

	public void moveX(float magnitude) {
		if (Math.abs(body.getLinearVelocity().x) < 3.5) {
			body.applyLinearImpulse(new Vec2(magnitude, 0), body.getPosition());
		}
	}

	public void moveY(float magnitude) {
		body.applyLinearImpulse(new Vec2(0, magnitude), body.getPosition());
	}

	public void setX(float x) {
		this.x = x;
	}

	public void setY(float y) {
		this.y = y;
	}

	@Override
	public void destroy(World world) {
		// TODO Auto-generated method stub
		
	}
}
